"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _TreeNode = _interopRequireDefault(require("./TreeNode"));
/**
 * 树
 */
class Tree {
  uniqueKey = 'key';
  childrenKey = 'children';
  nodes = [];

  /** 基于扁平化的树数据生成树实例 */
  static createInstanceFromFlattenData(items, options) {
    const {
      uniqueKey = 'key',
      parentKey = 'parentKey'
    } = options ?? {};
    const map = {};
    items.forEach(item => {
      map[item[uniqueKey]] = {
        ...item
      };
    });
    items.forEach(item => {
      if (item[parentKey]) {
        const parent = map[item[parentKey]];
        if (!parent.__children) parent.__children = [];
        parent.__children.push(map[item[uniqueKey]]);
      }
    });
    const firstLevelItems = Object.keys(map).filter(key => !map[key][parentKey]).map(key => map[key]);
    return new Tree(firstLevelItems, {
      uniqueKey,
      childrenKey: '__children'
    });
  }
  constructor(data, options) {
    if (options?.uniqueKey) this.uniqueKey = options.uniqueKey;
    if (options?.childrenKey) this.childrenKey = options.childrenKey;
    this.nodes = data.map(it => new _TreeNode.default(it, {
      uniqueKey: this.uniqueKey,
      childrenKey: this.childrenKey,
      tree: this
    }));
  }

  /** @todo 暂时每次访问均使用新的引用，以使视图更新 */
  get treeData() {
    return [...this.nodes];
  }

  /** 遍历 */
  forEach(iteratee, options = {
    mode: 'pre'
  }) {
    this.nodes.forEach(childNode => childNode.forEach(iteratee, options));
  }

  /** 过滤，仅包含匹配条件的节点 */
  filter(predicate, options = {
    mode: 'pre',
    isTree: false
  }) {
    let result = [];
    this.nodes.forEach(childNode => {
      const filtered = childNode.filter(predicate, options);
      result = result.concat(filtered);
    });
    return result;
  }

  /** 遍历转换 */
  map(convert) {
    let result = [];
    this.nodes.forEach(childNode => {
      const converted = childNode.map(convert);
      result = result.concat(converted);
    });
    return result;
  }

  /** 转数组 */
  toArray() {
    return this.map(node => node);
  }

  /** 转键值对映射 */
  toMap() {
    const result = {};
    this.forEach(node => {
      result[node.key] = node;
    });
    return result;
  }
  get length() {
    return this.toArray().length;
  }

  /** 是否包含 */
  has(predicate) {
    return this.nodes.some(childNode => {
      return childNode.has(typeof predicate === 'string' ? node => node.key === predicate : predicate);
    });
  }

  /** 通过匹配规则查找 */
  query(predicate) {
    let result;
    this.nodes.some(childNode => {
      const found = childNode.query(typeof predicate === 'string' ? node => node.key === predicate : predicate);
      if (found) {
        result = found;
        return true;
      }
    });
    return result;
  }

  /** 获取子孙节点，平铺数组形式 */
  getPosterityNodes(node) {
    if (node) {
      return node.toArray().filter(it => it.key !== node.key);
    } else {
      return this.toArray();
    }
  }

  /** 获取所有叶子节点 */
  getMaybeLeafNodes(node) {
    if (node) {
      return node.filter(it => it.isMaybeLeaf);
    } else {
      return this.filter(it => it.isMaybeLeaf);
    }
  }

  /** 尾部添加子节点（不改变原始数据） */

  append(node, data) {
    if (node instanceof _TreeNode.default) {
      if (!data) throw new Error('data muse not be undefined');
      if (this.has(data[this.uniqueKey])) {
        throw new Error(`${data[this.uniqueKey]} is existed already`);
      }
      node.append(data);
    } else {
      if (this.has(node[this.uniqueKey])) {
        throw new Error(`${node[this.uniqueKey]} is existed already`);
      }
      this.nodes.push(new _TreeNode.default(node, {
        uniqueKey: this.uniqueKey,
        childrenKey: this.childrenKey,
        tree: this
      }));
    }
    return this;
  }

  /** 尾部添加子节点列表（不改变原始数据） */

  appendChildren(node, datas) {
    if (node instanceof _TreeNode.default) {
      if (!datas) throw new Error('datas muse not be undefined');
      datas.forEach(data => {
        if (this.has(data[this.uniqueKey])) {
          throw new Error(`${data[this.uniqueKey]} is existed already`);
        }
      });
      node.appendChildren(datas);
    } else {
      node.forEach(data => {
        if (this.has(data[this.uniqueKey])) {
          throw new Error(`${data[this.uniqueKey]} is existed already`);
        }
      });
      node.forEach(data => {
        const nodeToAppend = new _TreeNode.default(data, {
          uniqueKey: this.uniqueKey,
          childrenKey: this.childrenKey,
          tree: this
        });
        this.nodes.push(nodeToAppend);
      });
    }
    return this;
  }

  /** 头部添加子节点（不改变原始数据） */

  prepend(node, data) {
    if (node instanceof _TreeNode.default) {
      if (!data) throw new Error('data muse not be undefined');
      if (this.has(data[this.uniqueKey])) {
        throw new Error(`${data[this.uniqueKey]} is existed already`);
      }
      node.prepend(data);
    } else {
      if (this.has(node[this.uniqueKey])) {
        throw new Error(`${node[this.uniqueKey]} is existed already`);
      }
      this.nodes.unshift(new _TreeNode.default(node, {
        uniqueKey: this.uniqueKey,
        childrenKey: this.childrenKey,
        tree: this
      }));
    }
    return this;
  }

  /** 头部添加子节点列表（不改变原始数据） */

  prependChildren(node, datas) {
    if (node instanceof _TreeNode.default) {
      if (!datas) throw new Error('datas muse not be undefined');
      datas.forEach(data => {
        if (this.has(data[this.uniqueKey])) {
          throw new Error(`${data[this.uniqueKey]} is existed already`);
        }
      });
      if (datas) node.prependChildren(datas);
    } else {
      node.forEach(data => {
        if (this.has(data[this.uniqueKey])) {
          throw new Error(`${data[this.uniqueKey]} is existed already`);
        }
      });
      node.reverse().forEach(data => {
        const nodeToPrepend = new _TreeNode.default(data, {
          uniqueKey: this.uniqueKey,
          childrenKey: this.childrenKey,
          tree: this
        });
        this.nodes.unshift(nodeToPrepend);
      });
    }
    return this;
  }

  /** 指定节点前插入节点（不改变原始数据） */
  insertBefore(node, data) {
    node.before(data);
    return this;
  }

  /** 指定节点后插入节点（不改变原始数据） */
  insertAfter(node, data) {
    node.after(data);
    return this;
  }

  /** 交换节点，不限制层级（不改变原始数据） */
  exchange(aNode, bNode) {
    aNode?.replaceWith(bNode?.origin);
    bNode?.replaceWith(aNode?.origin);
    return this;
  }

  /** 删除节点（不改变原始数据） */
  remove(node) {
    node.remove();
    return this;
  }
}
exports.default = Tree;